import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
import glob
import sys

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

def read_results():
    """读取所有结果文件并合并数据"""
    print("开始读取结果文件...")
    results = []
    
    # 获取当前脚本所在目录
    current_dir = os.path.dirname(os.path.abspath(__file__))
    print(f"当前目录: {current_dir}")
    
    # 构建数据目录路径
    data_dir = os.path.join(current_dir, '..', 'data')
    print(f"数据目录: {data_dir}")
    
    # 检查数据目录是否存在
    if not os.path.exists(data_dir):
        print(f"错误：数据目录 {data_dir} 不存在！")
        sys.exit(1)
    
    # 列出数据目录中的所有文件
    print("\n数据目录中的文件:")
    for file in os.listdir(data_dir):
        print(f"  - {file}")
    
    # 搜索结果文件
    pattern = os.path.join(data_dir, 'results_*_*.csv')
    print(f"\n搜索模式: {pattern}")
    
    files = glob.glob(pattern)
    print(f"找到 {len(files)} 个结果文件:")
    for file in files:
        print(f"  - {file}")
    
    if not files:
        print("错误：没有找到任何结果文件！")
        sys.exit(1)
    
    # 读取每个文件
    for file in files:
        print(f"\n读取文件: {file}")
        try:
            # 读取CSV文件，不使用标题行
            df = pd.read_csv(file, header=None, 
                           names=['Algorithm', 'Items', 'Capacity', 'Value', 'Time', 'Memory'])
            print(f"成功读取 {len(df)} 行数据")
            print("数据预览:")
            print(df.head())
            results.append(df)
        except Exception as e:
            print(f"读取文件 {file} 时出错: {str(e)}")
            import traceback
            traceback.print_exc()
    
    if not results:
        print("错误：没有成功读取任何数据！")
        sys.exit(1)
    
    print("\n合并数据...")
    combined_data = pd.concat(results, ignore_index=True)
    print(f"合并后共有 {len(combined_data)} 行数据")
    print("\n合并后的数据预览:")
    print(combined_data.head())
    return combined_data

def plot_time_comparison(data):
    """绘制执行时间比较图"""
    print("\n生成执行时间比较图...")
    plt.figure(figsize=(12, 8))
    sns.set_style("whitegrid")
    sns.lineplot(data=data, x='Items', y='Time', hue='Algorithm', marker='o', linewidth=2)
    plt.title('不同算法执行时间比较', fontsize=14, pad=20)
    plt.xlabel('物品数量', fontsize=12)
    plt.ylabel('执行时间 (ms)', fontsize=12)
    plt.yscale('log')  # 使用对数刻度
    plt.grid(True, alpha=0.3)
    plt.legend(fontsize=10)
    plt.tight_layout()
    plt.savefig('time_comparison.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("执行时间比较图已保存")

def plot_memory_comparison(data):
    """绘制内存使用比较图"""
    print("\n生成内存使用比较图...")
    plt.figure(figsize=(12, 8))
    sns.set_style("whitegrid")
    sns.lineplot(data=data, x='Items', y='Memory', hue='Algorithm', marker='o', linewidth=2)
    plt.title('不同算法内存使用比较', fontsize=14, pad=20)
    plt.xlabel('物品数量', fontsize=12)
    plt.ylabel('内存使用 (bytes)', fontsize=12)
    plt.yscale('log')  # 使用对数刻度
    plt.grid(True, alpha=0.3)
    plt.legend(fontsize=10)
    plt.tight_layout()
    plt.savefig('memory_comparison.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("内存使用比较图已保存")

def plot_value_comparison(data):
    """绘制总价值比较图"""
    print("\n生成总价值比较图...")
    plt.figure(figsize=(12, 8))
    sns.set_style("whitegrid")
    sns.lineplot(data=data, x='Items', y='Value', hue='Algorithm', marker='o', linewidth=2)
    plt.title('不同算法获得的总价值比较', fontsize=14, pad=20)
    plt.xlabel('物品数量', fontsize=12)
    plt.ylabel('总价值', fontsize=12)
    plt.grid(True, alpha=0.3)
    plt.legend(fontsize=10)
    plt.tight_layout()
    plt.savefig('value_comparison.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("总价值比较图已保存")

def plot_value_difference(data):
    """绘制算法间价值差异百分比"""
    print("\n生成价值差异百分比图...")
    # 计算每个物品数量下两种算法的价值差异百分比
    diff_data = []
    for items in sorted(data['Items'].unique()):
        dp_value = data[(data['Items'] == items) & (data['Algorithm'] == 'Dynamic Programming')]['Value'].iloc[0]
        greedy_value = data[(data['Items'] == items) & (data['Algorithm'] == 'Greedy')]['Value'].iloc[0]
        diff_percent = (dp_value - greedy_value) / dp_value * 100
        diff_data.append({'Items': items, 'Difference': diff_percent})
    
    diff_df = pd.DataFrame(diff_data)
    
    plt.figure(figsize=(12, 8))
    sns.set_style("whitegrid")
    sns.lineplot(data=diff_df, x='Items', y='Difference', marker='o', linewidth=2, color='red')
    plt.title('动态规划与贪心算法的价值差异百分比', fontsize=14, pad=20)
    plt.xlabel('物品数量', fontsize=12)
    plt.ylabel('差异百分比 (%)', fontsize=12)
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.savefig('value_difference.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("价值差异百分比图已保存")

def create_summary_table(data):
    """创建汇总表格"""
    print("\n生成汇总表格...")
    summary = data.groupby(['Items', 'Algorithm']).agg({
        'Value': 'mean',
        'Time': 'mean',
        'Memory': 'mean'
    }).round(2)
    
    # 保存为CSV文件
    summary.to_csv('summary_table.csv')
    print("汇总表格(CSV)已保存")
    
    # 创建HTML表格
    html_table = summary.to_html()
    with open('summary_table.html', 'w', encoding='utf-8') as f:
        f.write(html_table)
    print("汇总表格(HTML)已保存")

def main():
    try:
        # 获取当前脚本所在目录
        current_dir = os.path.dirname(os.path.abspath(__file__))
        print(f"脚本所在目录: {current_dir}")
        
        # 创建输出目录
        plots_dir = os.path.join(current_dir, 'plots')
        print(f"创建输出目录: {plots_dir}")
        os.makedirs(plots_dir, exist_ok=True)
        
        # 切换到输出目录
        os.chdir(plots_dir)
        print(f"已切换到输出目录: {plots_dir}")
        
        # 读取数据
        data = read_results()
        print(f"\n读取到 {len(data)} 条数据记录")
        
        # 生成图表
        plot_time_comparison(data)
        plot_memory_comparison(data)
        plot_value_comparison(data)
        plot_value_difference(data)
        
        # 创建汇总表格
        create_summary_table(data)
        
        print("\n可视化完成！图表已保存到 plots 目录")
        print(f"输出目录: {plots_dir}")
        
    except Exception as e:
        print(f"\n发生错误: {str(e)}")
        import traceback
        traceback.print_exc()
        sys.exit(1)

if __name__ == '__main__':
    main() 